package me.j360.springboot.simple;

import com.atomikos.icatch.jta.UserTransactionImp;
import com.atomikos.icatch.jta.UserTransactionManager;
import com.atomikos.jms.AtomikosConnectionFactoryBean;
import com.mysql.jdbc.jdbc2.optional.MysqlXADataSource;
import me.j360.springboot.simple.bean.DestinationConstant;
import me.j360.springboot.simple.bean.config.J360WebMvcConfig;
import me.j360.springboot.simple.interceptors.hibernate.EntityInterceptor;
import org.apache.activemq.ActiveMQXAConnectionFactory;
import org.apache.activemq.command.ActiveMQQueue;
import org.apache.catalina.Context;
import org.hibernate.cfg.DefaultComponentSafeNamingStrategy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.embedded.*;
import org.springframework.boot.context.embedded.tomcat.TomcatContextCustomizer;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.web.SpringBootServletInitializer;
import org.springframework.boot.jta.atomikos.AtomikosDataSourceBean;
import org.springframework.boot.orm.jpa.EntityScan;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.http.HttpStatus;
import org.springframework.jdbc.datasource.embedded.DataSourceFactory;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.config.JmsListenerContainerFactory;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.listener.DefaultMessageListenerContainer;
import org.springframework.jms.listener.MessageListenerContainer;
import org.springframework.jms.support.converter.MessageConverter;
import org.springframework.jms.support.destination.DestinationResolver;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.session.web.http.SessionRepositoryFilter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.jta.JtaTransactionManager;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.filter.DelegatingFilterProxy;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import redis.clients.jedis.JedisPoolConfig;

import javax.jms.ConnectionFactory;
import javax.jms.Queue;
import javax.jms.Session;
import javax.servlet.*;
import javax.sql.DataSource;
import javax.sql.XADataSource;
import javax.transaction.TransactionManager;
import javax.transaction.UserTransaction;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.Properties;

/**
 * Created with springbootweb -> me.j360.springboot.simple.
 * User: min_xu
 * Date: 2015/7/29
 * Time: 10:18
 * 说明：等同于SpringContext.xml作用
 */
@EntityScan("me.j360")
@ComponentScan("me.j360")
@EnableAutoConfiguration
@Configuration
@EnableTransactionManagement
@EnableRedisHttpSession
//@ImportResource("classpath:hibernate.xml")
public class J360MainConfiguration extends SpringBootServletInitializer {
    //1、使用SpringBootServletInitializer
    //2、使用WebMvcConfigurerAdapter


    @Autowired
    private EntityInterceptor entityInterceptor;

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(J360MainConfiguration.class);
    }
    @Autowired
    private DataSource dataSource;

    @Bean
    public LocalSessionFactoryBean sessionFactory() throws Throwable {
        LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
        sessionFactory.setDataSource(customerDataSource());
        sessionFactory.setPackagesToScan("me.j360");
        Properties properties = new Properties();
        properties.setProperty("hibernate.hbm2ddl.auto","update");
        sessionFactory.setHibernateProperties(properties);
        //sessionFactory.setNamingStrategy(new DefaultComponentSafeNamingStrategy());
        sessionFactory.setEntityInterceptor(entityInterceptor);
        sessionFactory.setJtaTransactionManager(transactionManager());
        return sessionFactory;
    }

    @Bean(name = "customerDataSource")
    public DataSource customerDataSource() {
        MysqlXADataSource mysqlXaDataSource = new MysqlXADataSource();
        mysqlXaDataSource.setUrl("jdbc:mysql://localhost:3306/springboot-web");
        mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);
        mysqlXaDataSource.setPassword("root");
        mysqlXaDataSource.setUser("root");

        AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
        xaDataSource.setXaDataSource(mysqlXaDataSource);
        return xaDataSource;
    }



    //To add filters to your main application just create @Bean definitions for Filter or FilterRegistrationBean instances.
    //@Bean
    public CharacterEncodingFilter characterEncodingFilter() {
        final CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
        characterEncodingFilter.setEncoding("UTF-8");
        characterEncodingFilter.setForceEncoding(true);
        return characterEncodingFilter;
    }
    //另外一种方法
    @Bean
    public FilterRegistrationBean j360FilterRegistration() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(characterEncodingFilter());
        return registration;
    }

    @Bean
    public EmbeddedServletContainerFactory servletContainer() {
        TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();
        factory.setTomcatContextCustomizers(Arrays.asList(new CustomCustomizer()));
        factory.addErrorPages(
                new ErrorPage(HttpStatus.UNAUTHORIZED,"/WEB-INF/views/unprot/common/errors/containerError.jsp"),
                new ErrorPage(HttpStatus.NOT_FOUND,"/WEB-INF/views/unprot/common/errors/containerError.jsp"),
                new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR,"/WEB-INF/views/unprot/common/errors/containerError.jsp"));
        /*MimeMappings mappings = new MimeMappings(MimeMappings.DEFAULT);
        mappings.add("xsd", "text/xml");
        mappings.add("wsdl", "text/xml");
        factory.setMimeMappings(mappings);*/
        return factory;
    }

    static class CustomCustomizer implements TomcatContextCustomizer {
        @Override
        public void customize(Context context) {
            context.setUseHttpOnly(true);
            context.addWelcomeFile("home.html");
        }
    }

    @Bean
    public ServletContextInitializer initializer() {
        return new ServletContextInitializer() {
            @Override
            public void onStartup(ServletContext servletContext) throws ServletException {

            }
        };
    }


    //添加csf ws
    /*@Bean
    public ServletRegistrationBean cxf() {
        return new ServletRegistrationBean(new CXFServlet(), "/cxf*//*");
    }*/


    //@Bean
    //@Order(value = 0)
    public FilterRegistrationBean sessionRepositoryFilterRegistration(SessionRepositoryFilter springSessionRepositoryFilter) {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setFilter(new DelegatingFilterProxy(springSessionRepositoryFilter));
        filterRegistrationBean.setUrlPatterns(Arrays.asList("/*"));
        return filterRegistrationBean;
    }

    //此处需要配置Jedis信息，默认的是本地的localhost
    //@Bean
    public JedisConnectionFactory connectionFactory() {
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        return new JedisConnectionFactory(jedisPoolConfig);
    }


    @Bean
    public Queue queue() {
        return new ActiveMQQueue("sample.queue");
    }



    @Bean(name = "userTransaction")
    public UserTransaction userTransaction() throws Throwable {
        UserTransactionImp userTransactionImp = new UserTransactionImp();
        userTransactionImp.setTransactionTimeout(10000);
        return userTransactionImp;
    }

    @Bean(name = "atomikosTransactionManager", initMethod = "init", destroyMethod = "close")
    public TransactionManager atomikosTransactionManager() throws Throwable {
        UserTransactionManager userTransactionManager = new UserTransactionManager();
        userTransactionManager.setForceShutdown(false);
        return userTransactionManager;
    }

    @Bean(name = "transactionManager")
    @DependsOn({ "userTransaction", "atomikosTransactionManager" })
    public PlatformTransactionManager transactionManager() throws Throwable {
        UserTransaction userTransaction = userTransaction();
        TransactionManager atomikosTransactionManager = atomikosTransactionManager();
        return new JtaTransactionManager(userTransaction, atomikosTransactionManager);
    }


    @Bean
    public AtomikosConnectionFactoryBean atomikosConnectionFactoryBean(){
        AtomikosConnectionFactoryBean atomikosConnectionFactoryBean = new AtomikosConnectionFactoryBean();
        //atomikosConnectionFactoryBean.setBeanName("atomikosConnectionFactoryBean");
        ActiveMQXAConnectionFactory activeMQXAConnectionFactory = new ActiveMQXAConnectionFactory();
        activeMQXAConnectionFactory.setBrokerURL("tcp://localhost:61616");
        activeMQXAConnectionFactory.setXaAckMode(Session.SESSION_TRANSACTED);
        atomikosConnectionFactoryBean.setUniqueResourceName("atomikosConnectionFactoryBean");
        atomikosConnectionFactoryBean.setXaConnectionFactory(activeMQXAConnectionFactory);
        atomikosConnectionFactoryBean.setPoolSize(3);

        return atomikosConnectionFactoryBean;
    }
/*
    @Bean
    public JmsTemplate jmsTemplate(){
        JmsTemplate jmsTemplate = new JmsTemplate();
        jmsTemplate.setConnectionFactory(atomikosConnectionFactoryBean());
        jmsTemplate.setSessionTransacted(true);
        jmsTemplate.setReceiveTimeout(2000);
        return jmsTemplate;
    }

    @Bean
    public JmsMessagingTemplate jmsMessagingTemplate(){
        JmsMessagingTemplate jmsMessagingTemplate = new JmsMessagingTemplate();
        jmsMessagingTemplate.setJmsTemplate(jmsTemplate());
        return jmsMessagingTemplate;
    }*/

    @Bean
    public JmsListenerContainerFactory jmsListenerContainerFactory() throws Throwable {
        DefaultJmsListenerContainerFactory jmsListenerContainerFactory = new DefaultJmsListenerContainerFactory();
        jmsListenerContainerFactory.setConnectionFactory(atomikosConnectionFactoryBean());
        jmsListenerContainerFactory.setTransactionManager(transactionManager());
        jmsListenerContainerFactory.setSessionTransacted(true);
        jmsListenerContainerFactory.setSessionAcknowledgeMode(Session.SESSION_TRANSACTED);
        return jmsListenerContainerFactory;
    }

}
